/*
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.impl.orbutil;

import java.util.Arrays;

public abstract class ObjectWriter {

  public static ObjectWriter make(boolean isIndenting,
      int initialLevel, int increment) {
    if (isIndenting) {
      return new IndentingObjectWriter(initialLevel, increment);
    } else {
      return new SimpleObjectWriter();
    }
  }

  public abstract void startObject(Object obj);

  public abstract void startElement();

  public abstract void endElement();

  public abstract void endObject(String str);

  public abstract void endObject();

  public String toString() {
    return result.toString();
  }

  public void append(boolean arg) {
    result.append(arg);
  }

  public void append(char arg) {
    result.append(arg);
  }

  public void append(short arg) {
    result.append(arg);
  }

  public void append(int arg) {
    result.append(arg);
  }

  public void append(long arg) {
    result.append(arg);
  }

  public void append(float arg) {
    result.append(arg);
  }

  public void append(double arg) {
    result.append(arg);
  }

  public void append(String arg) {
    result.append(arg);
  }

//=================================================================================================
// Implementation
//=================================================================================================

  protected StringBuffer result;

  protected ObjectWriter() {
    result = new StringBuffer();
  }

  protected void appendObjectHeader(Object obj) {
    result.append(obj.getClass().getName());
    result.append("<");
    result.append(System.identityHashCode(obj));
    result.append(">");
    Class compClass = obj.getClass().getComponentType();

    if (compClass != null) {
      result.append("[");
      if (compClass == boolean.class) {
        boolean[] arr = (boolean[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == byte.class) {
        byte[] arr = (byte[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == short.class) {
        short[] arr = (short[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == int.class) {
        int[] arr = (int[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == long.class) {
        long[] arr = (long[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == char.class) {
        char[] arr = (char[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == float.class) {
        float[] arr = (float[]) obj;
        result.append(arr.length);
        result.append("]");
      } else if (compClass == double.class) {
        double[] arr = (double[]) obj;
        result.append(arr.length);
        result.append("]");
      } else { // array of object
        java.lang.Object[] arr = (java.lang.Object[]) obj;
        result.append(arr.length);
        result.append("]");
      }
    }

    result.append("(");
  }

  /**
   * Expected patterns:
   * startObject endObject( str )
   * header( elem )\n
   * startObject ( startElement append* endElement ) * endObject
   * header(\n
   * append*\n *
   * )\n
   */
  private static class IndentingObjectWriter extends ObjectWriter {

    private int level;
    private int increment;

    public IndentingObjectWriter(int initialLevel, int increment) {
      this.level = initialLevel;
      this.increment = increment;
      startLine();
    }

    private void startLine() {
      char[] fill = new char[level * increment];
      Arrays.fill(fill, ' ');
      result.append(fill);
    }

    public void startObject(java.lang.Object obj) {
      appendObjectHeader(obj);
      level++;
    }

    public void startElement() {
      result.append("\n");
      startLine();
    }

    public void endElement() {
    }

    public void endObject(String str) {
      level--;
      result.append(str);
      result.append(")");
    }

    public void endObject() {
      level--;
      result.append("\n");
      startLine();
      result.append(")");
    }
  }

  private static class SimpleObjectWriter extends ObjectWriter {

    public void startObject(java.lang.Object obj) {
      appendObjectHeader(obj);
      result.append(" ");
    }

    public void startElement() {
      result.append(" ");
    }

    public void endObject(String str) {
      result.append(str);
      result.append(")");
    }

    public void endElement() {
    }

    public void endObject() {
      result.append(")");
    }
  }
}
